<?php

/**
 * 
 * \file luminous_common_grammars.php
 * \brief Grammar definitions (and examples) for common languages
 * 
 * \example luminous_common_grammars.php 
 * Built in grammar definitions, browse these to get a feel for how to write
 *      your own.
 * 
 * \todo clean up regex rules with proper char classes.
 * 
 */

 
require_once('luminous_grammar.class.php');


/**
 * \return a generic regex literal regex rule
 */ 
function luminous_generic_regex_literal($modifiers, 
  $preceding_chars = "[
                        \(\[,=:;\?!\|\&~
                      ]")
{
  return "/
  (?<=($preceding_chars))
  [\s]* 
  \/(?![\/\*])
  (?:.*?[^\\\])*?
  (?:\\\\\\\\)*\/
  [$modifiers]*/x";  
}

/**
 * \return a generic string literal regex, where it uses doubling of
 * delimiters to escape.
 */ 
function luminous_generic_str_literal_sql($delimiter='\'')
{
  return 
  "/
  (?:$delimiter$delimiter)
  |
  (?:(?:$delimiter.*?(?<!$delimiter)$delimiter)(?!$delimiter))
  /sx";
}

/// \cond 

// no point generating class docs for all of these.


/* I don't actually know ActionScript so there's definitely room for improvement
 * in this one
 */
class LuminousGrammarActionscript extends LuminousGrammar
{
  public $keywords = array('as',
  'break',
  'case',
  'catch',
  'class',
  'const',
  'continue',
  'default',
  'delete',
  'do',
  'else',
  'extends',
  'false',
  'finally',
  'for',
  'function',
  'if',
  'implements',
  'import',
  'in',
  'instanceof',
  'interface',
  'internal',
  'is',
  'native',
  'new',
  'null',
  'package',
  'private',
  'protected',
  'public',
  'return',
  'super',
  'switch',
  'this',
  'throw',
  'to',
  'true',
  'try',
  'typeof',
  'use',
  'void',
  'while',
  'with'
  );
  
  public $types = array('String', 'var');
  function __construct()
  {
    $this->delimited_types = array(
      new LuminousDelimiterRule('DOCCOMMENT', 0, '/**', '*/', 
        'luminous_type_callback_doccomment'),  
      new LuminousDelimiterRule('COMMENT', 0, '/*', '*/'),
      new LuminousDelimiterRule('COMMENT', LUMINOUS_STOP_AT_END, '//', "\n"),
      new LuminousDelimiterRule('STRING', 0, '"', '"',
        'luminous_type_callback_generic_string'),
      new LuminousDelimiterRule('STRING', 0, "'", "'",
        'luminous_type_callback_generic_string'),
      
      new LuminousDelimiterRule('REGEX', LUMINOUS_COMPLETE|LUMINOUS_REGEX,
        luminous_generic_regex_literal("gimsx"), null,
        'luminous_type_callback_generic_string')
      
    );
    
    $this->SetInfoLanguage("as");
    
    $this->SetSimpleTypeRules();
  }
}


class LuminousGrammarActionscriptEmbedded extends LuminousGrammarActionscript
{
  public function __construct()
  {
    parent::__construct();
    
    $this->simple_types = array_merge( 
      array(
        new LuminousSimpleRule('COMMENT', LUMINOUS_REGEX,
        '/(?:&lt;!\[CDATA\[)|(?:\]\]&gt;)/')
        ),
        $this->simple_types
        );
    
    $this->ignore_outside = array(
      new LuminousDelimiterRule(null, LUMINOUS_REGEX|LUMINOUS_EXCLUDE, 
      '/&lt;[\s]*mx:Script[\s]*&gt;/i',
      '/&lt;[\s]*\/[\s]*mx:Script[\s]*&gt;/i')
      );
      
     $this->child_grammar = new LuminousGrammarHTML();
  }
  
}



class LuminousGrammarCpp extends LuminousGrammar
{  
  public $keywords = array('auto', 'break', 'continue', 'else', 'for', 'switch', 
    'case', 'default', 'goto', 'register', 'typedef', 'volatile', 'do', 
    'extern', 'if', 'return', 'static', 'union', 'while', 'asm', 'dynamic_cast', 
    'namespace', 'reinterpret_cast', 'try', 'explicit', 'new', 'static_cast', 
    'typeid','catch', 'operator', 'template', 'typename', 'class', 'friend', 
    'private', 'this', 'using', 'const_cast', 'inline', 'public', 'throw', 
    'virtual', 'delete', 'mutable', 'protected');
        
  public $types = array('bool', 'double', 'enum', 'float', 'int', 'short', 
    'struct', 'unsigned', 'long', 'signed', 'void', 'char', 'union', 'FALSE', 
    'TRUE', 'false', 'true', 'wchar_t', 'const');
    
  public $operators = array('\+', '\*', '-', '\/', '=', '&gt;', '&lt;', '=',
        '!', '%', '&amp;', '\|', '~', '\^', '\[', '\]');
        
  public $functions = array('sizeof', 'malloc', 'free');
  
  public function __construct()
  {
    $this->SetInfoAuthor( 
      array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
        'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('cpp');
    $this->SetInfoVersion('1.0');
    
    
    $this->delimited_types = array(
      
      new LuminousDelimiterRule('DOCCOMMENT', 0, '/**', '*/', 
        "luminous_type_callback_doccomment"),
      new LuminousDelimiterRule("DOCCOMMENT", 0, "/*!", "*/",
        "luminous_type_callback_doccomment"),
      new LuminousDelimiterRule("DOCCOMMENT", 0, "//!", "\n",
        "luminous_type_callback_doccomment"),
      new LuminousDelimiterRule("DOCCOMMENT", 0, "///", "\n",
        "luminous_type_callback_doccomment"),
      
      new LuminousDelimiterRule('COMMENT', 0, '/*', '*/'),
      new LuminousDelimiterRule('COMMENT', 0, '//', "\n"),
      
      new LuminousDelimiterRule('COMMENT', 0, '#if 0', '#endif'),      
      new LuminousDelimiterRule('STRING', 0, '"', '"',
        "luminous_type_callback_cstring"),
      new LuminousDelimiterRule('CHARACTER', 0, '\'', '\'',
        'luminous_type_callback_cstring'),
      new LuminousDelimiterRule('PREPROCESSOR', 0, '#', "\n")
    ); 
    
    $this->SetSimpleTypeRules();
  }
}





// TODO this
class LuminousGrammarGeneric extends LuminousGrammar
{
  
  
}


class LuminousGrammarLatex extends LuminousGrammar
{
  
  public $type_regex = "/\\\(%TYPE)/";
  public $types = array('alpha', 'theta', 'tau', 
  'beta', 'vartheta', 'pi', 'upsilon', 
  'gamma', 'gamma', 'varpi', 'phi', 
  'delta', 'kappa', 'rho', 'varphi', 
  'epsilon', 'lambda', 'varrho', 'chi', 
  'varepsilon', 'mu', 'sigma', 'psi',
  'zeta', 'nu', 'varsigma', 'omega', 
  'eta', 'xi', 
  'Gamma', 'Lambda', 'Sigma', 'Psi',
  'Delta', 'Xi', 'Upsilon', 'Omega', 
  'Theta', 'Pi', 'Phi');
  

  
  public $operators = array();
  
  public $numeric_regex = null;
  
  public function __construct()
  {
    $this->SetInfoLanguage('latex');
    $this->delimited_types = array(
      new LuminousDelimiterRule('COMMENT', LUMINOUS_REGEX|LUMINOUS_COMPLETE, 
        '/(?<!\\\)%.*?$/m'),
      // this definitely shouldn't be variable.  
      new LuminousDelimiterRule('VARIABLE', LUMINOUS_REGEX|LUMINOUS_COMPLETE,
        '/(?<=[^\\\]\[)(?:[^\[\\\]+?)(?=(\]))/', null, null),
      
      // LaTeX allows nesting, which we can't handle with a regex.
      new LuminousDelimiterRule('VALUE', LUMINOUS_REGEX|LUMINOUS_COMPLETE,
        '/(?<=[^\\\]\{)(?:[^\{\\\]+?)(?=(\}))/', null, null)
     );
     


    $this->SetSimpleTypeRules();
    
    $keyword_regex = "/\\\(%KEYWORD)/";
    
    /// I'm trying to keep this more oriented towards common layout and 
    /// formatting commands, not all the maths stuff, will be caught by the 
    /// general rule.
    /// But I haven't used LaTeX much, and when I did it was always for maths
    /// (the irony).
    $keywords = array('@', 'begin', 'DisableLigatures', 'end', 'emph', 
      'fbox', 'footnotesize', 'frenchspacing', '[hH]uge', 'hyphonation', 
      '[lL]arge', 'LARGE', 'ldots', 'mathrm', 'mbox', 'newcommand', 'normalem', 
      'normalsize', 'oldstylenums', 'scriptsize', 'small', 'sout', 'tiny', 
      'text(normal|rm|sf|tt|up|it|sl|sc|bf|md|(super|sub)script|color)', 
      'ulem', 'underline', 'usepackage', 'uwave');
  
    $this->simple_types[] = new LuminousSimpleRuleList('LATEX_FUNCTION',
      LUMINOUS_REGEX, $keywords, $keyword_regex, '%KEYWORD');
    

    
    
    // kind of a generic thing to catch everything else.
    $this->simple_types[] = 
      new LuminousSimpleRule('FUNCTION', LUMINOUS_REGEX, 
        '/
          (?:\\\)
          (?:
            (?:[[:alnum:]]+)
            | [\-\\\\{\}%]
            
            )
            
        /x');
        
    $this->simple_types[] = new LuminousSimpleRuleList('LATEX_OPERATOR', 
      LUMINOUS_REGEX, array('\[', '\]', '\{', '\}'), '/%OP/', '%OP');
  }
  
}



/// \todo this could do with some work, but I don't know Pascal.
class LuminousGrammarPascal extends LuminousGrammar

{
  public $case_insensitive = true;
  
  public $keywords = array(
    'And', 'Downto', 'If', 'Or', 'Then',
    'Array', 'Else', 'In', 'Packed', 'To',
    'Begin', 'End', 'Label', 'Procedure', 'Type',
    'Case', 'File', 'Mod', 'Program', 'Until',
    'Const', 'For', 'Nil', 'Record', 'Var',
    'Div', 'Function', 'Not', 'Repeat', 'While',
    'Do', 'Goto', 'Of', 'Set', 'With',
    'And_then', 'Import', 'Module', 'Otherwise', 'Qualified',
    'Bindable', 'Implementation', 'Only', 'Pow', 'Restricted',
    'Export', 'Interface', 'Or_else', 'Protected', 'Value',
    'Absolute', 'Destructor', 'Inline', 'Shl', 'Uses',
    'Asm', 'Implementation', 'Interface', 'Shr', 'Virtual',
    'Constructor', 'Inherited', 'Object', 'Unit', 'Xor',
    'as', 'exports', 'initialization', 'on', 'threadvar',
    'class', 'finalization', 'is', 'property', 'try',
    'except', 'finally', 'library', 'raise', 
    'dispose', 'exit', 'false', 'new', 'true',
    'Abstract', 'Constructor', 'Inherited', 'Object', 'View',
    'Class', 'Destructor', 'Is', 'Property', 'Virtual',
    'All', 'Asm', 'Inline', 
    'Module', 'Operator'
  );
  
  public $types = array(
    'Integer',
    'Shortint',
    'SmallInt',
    'Longint',
    'Longword',
    'Int64',
    'Byte',
    'Word',
    'Cardinal',
    'QWord',
    'Boolean',
    'ByteBool',
    'WordBool',
    'LongBool',
    'Char');
    
  
  public function __construct()
  {
    $this->SetInfoLanguage('pascal');
    
    $this->delimited_types = array(
      new LuminousDelimiterRule('COMMENT', 0, '{', '}'),
      new LuminousDelimiterRule('COMMENT', 0, '(*', '*)'),
      new LuminousDelimiterRule('COMMENT', 0, '//', "\n"),
      new LuminousDelimiterRule('STRING', LUMINOUS_REGEX|LUMINOUS_COMPLETE,
        luminous_generic_str_literal_sql()),
        new LuminousDelimiterRule('STRING', LUMINOUS_REGEX|LUMINOUS_COMPLETE,
        luminous_generic_str_literal_sql('"'))
    );
    
    $this->SetSimpleTypeRules();
    
  }
  
  
  
}


class LuminousGrammarPython extends LuminousGrammar
{
  public $operators = array('(?<![a-zA-Z0-9_])and(?![a-zA-Z0-9_])', 
    '(?<![a-zA-Z0-9_])not(?![a-zA-Z0-9_])', 
    '(?<![a-zA-Z0-9_])in(?![a-zA-Z0-9_])', 
    '(?<![a-zA-Z0-9_])is(?![a-zA-Z0-9_])', 
    '(?<![a-zA-Z0-9_])or(?![a-zA-Z0-9_])',
    '\+', '\*', '-', '\/', '=', '&gt;', '&lt;', '=','!', '%', '&amp;', '\|','~',
    '\^', '\[', '\]');
    
  public $keywords = array('del', 'for', 'raise', 'assert', 'elif', 'from', 
    'lambda', 'return', 'break', 'else', 'global', 'try', 'class', 'except', 
    'if', 'while','continue', 'exec', 'import', 'pass', 'yield', 'def', 
    'finally', 'print', 'as');
  
  // okay so these aren't really types but it makes it more colourful.
  public $types = array('False', 'True', 'None',
    'self',
    'int', 'float', 'long', 'complex',
    'str', 'unicode', 'list', 'tuple', 'buffer',
    'set', 'frozenset', 'dict',
    'memoryview',
    'Ellipsis',
  );
  
  public $functions = array('len', 'x?range');
    
  public $numeric_regex = '
    /(?<![a-zA-Z_0-9<])  
    (?:
      #hex 
      (?:0[xX][0-9A-Fa-f]+)
    |
      (?:0[bB][0-1]+)
    |
      (?:0[oO0][0-8]+)      
    | 
      # regular number
      (?:
        [0-9]+
        (?:
          # fraction
          \.(?:[0-9]+(?:[eE]?[0-9]+)?)
        )?
      )
      |
      (?:
        # or only after the point
        \.(?:[0-9]+(?:[eE]?[0-9]+)?)
      )
    )
    [jJlL]?
    /x';
    
  public function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
          'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('py');
    $this->SetInfoVersion('1.0');    
    
    $this->delimited_types = array(
      new LuminousDelimiterRule('SHEBANG', LUMINOUS_REGEX|LUMINOUS_COMPLETE, 
        "/^[\s]*#!.*?\n/"),
      new LuminousDelimiterRule('COMMENT', 0, '#', "\n"),
      
      # I think according to Python these are actually string literals, but
      # they tend to be used more for multiline commenting.
      new LuminousDelimiterRule('COMMENT', 0, '"""', '"""'),
      new LuminousDelimiterRule('COMMENT', 0, "'''", "'''"),
      
      new LuminousDelimiterRule('STRING', LUMINOUS_REGEX, 
      '/[ruRU]{0,2}\'/', '/\'/', 'luminous_type_callback_pystring'),
      
      new LuminousDelimiterRule('STRING', LUMINOUS_REGEX, 
      '/[ruRU]{0,2}"/', '/"/', 'luminous_type_callback_pystring')    
      );
      
    $this->type_callbacks = array(
      "STRING"=>"luminous_type_callback_cstring",
      );
    

    
    $this->SetSimpleTypeRules();
    
    
  }
}

class LuminousGrammarRuby extends LuminousGrammar
{
  public $operators =  array('(?<![a-zA-Z0-9])and(?![a-zA-Z0-9])', 
    '(?<![a-zA-Z0-9])not(?![a-zA-Z0-9])', '(?<![a-zA-Z0-9])in(?![a-zA-Z0-9])', 
    '(?<![a-zA-Z0-9])or(?![a-zA-Z0-9])', '\+', '\*', '-', '\/', '=',  '&gt;', 
    '&lt;', '=','!', '%', '&amp;', '\|', '~', '\^', '\[', '\]');
    
  public $keywords =  array("alias", "BEGIN", "(?<!=)begin", "break", "case",
    "class", "def","defined", "do", "else", "elsif", "END", "(?<!=)end", 
    "ensure", "false", "for", "if", "module", "next", "nil", "redo", "rescue", 
    "retry", "return", "self", "super", "then", "true", "undef", "unless",
    "until", "when", "while", "yield");
    
    public $types = array('false', 'nil', 'true');
      
    
  public function __construct()
  {
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('rb');
    $this->SetInfoVersion('1.0');        
    
    
    $this->delimited_types = array(
      new LuminousDelimiterRule("DOCCOMMENT", 
        LUMINOUS_REGEX|LUMINOUS_COMPLETE, "/^=begin(?:.*?)^=end/ms"),
        
      new LuminousDelimiterRule("COMMENT", 0, "#", "\n"),
      
      new LuminousDelimiterRule("STRING", 0, '"', '"',
        'luminous_type_callback_cstring'),
        
      new LuminousDelimiterRule("STRING", 0, "'", "'", 
        'luminous_type_callback_php_sstring'),
        
      new LuminousDelimiterRule("STRING", 
        LUMINOUS_DYNAMIC_DELIMS|LUMINOUS_COMPLETE|LUMINOUS_EXCLUDE, "%w"),
        
      new LuminousDelimiterRule("REGEX", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
          '/
      (?<=([\(\[,=:;\?!~]))
      [\s]* 
      \/
        (?:.*?[^\\\])*?
        (?:\\\\\\\\)*\/
      [iomx]*/x',
      null,
      'luminous_type_callback_generic_string'
      ),
      
      new LuminousDelimiterRule("REGEX", LUMINOUS_REGEX|LUMINOUS_DYNAMIC_DELIMS,
      '/%r[\s]*/s', '[iomx]*/', 'luminous_type_callback_generic_string')
    );
    

    $this->SetSimpleTypeRules();
    
  }
}

class LuminousGrammarRubyHTML extends LuminousGrammarRuby
{
  
  public function __construct()
  {
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('rhtml');
    $this->SetInfoVersion('1.0');        
    
    $this->child_grammar = new LuminousGrammarJavaScriptEmbedded();
    $this->ignore_outside = array(
      new LuminousDelimiterRule(null, LUMINOUS_REGEX|LUMINOUS_EXCLUDE,
      "/&lt;%=?/", "/%&gt;/")
      );
    parent::__construct();
  }
  
}



class LuminousGrammarHTMLText extends LuminousGrammar
{
  
  function __construct()
  {
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('htmltext');
    $this->SetInfoVersion('1.0');        
    
    $this->simple_types = array(
      new LuminousSimpleRule('ESC', LUMINOUS_REGEX, 
      "/(?:&amp;)(?:[a-z]+|(#[0-9]+));/i")
      );
  }  
}


class LuminousGrammarHTML extends LuminousGrammar
{
 function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('html');
    $this->SetInfoVersion('1.0');        
    
    $this->ignore_outside = array( 
      new LuminousDelimiterRule(null, 0, "&lt;", "&gt;")
    );
    $this->child_grammar = new LuminousGrammarHTMLText();
    
    $test = true;
    
    $this->delimited_types = array(      
      new LuminousDelimiterRule("COMMENT", LUMINOUS_END_IS_END,
      "&lt;!--", "--&gt;")
    );

    $this->delimited_types[] = new LuminousDelimiterRule("STRING", 
      LUMINOUS_REGEX|LUMINOUS_COMPLETE,
      "/
        (?:'')
        |
        (?:'.*?(?:'|(?=&[lg]t;)))
      /xs");
    
    $this->delimited_types[] = new LuminousDelimiterRule("STRING", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
    '/
    (?:"")|
    (?:".*?(?:"|(?=&gt;)))
    /xs');  
   

    $this->simple_types = array();      
      
    $this->simple_types[] = new LuminousSimpleRule("TYPE", LUMINOUS_REGEX,
    "/(?<=([\s]))(?:[a-z\-:]+)(?=([=]))/i");
    $this->simple_types[] = new LuminousSimpleRule("HTMLTAG", LUMINOUS_REGEX,
    "/(?<=(&lt;))(!?|\/?)[a-z0-9_\-\:]+/i");
    $this->simple_types[] = new LuminousSimpleRule('VALUE', LUMINOUS_REGEX,
    "/(?<=(=))[\s]*[^\s]+/i");      
      
      

  }
}

class LuminousGrammarCSS extends LuminousGrammar
{


  function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('css');
    $this->SetInfoVersion('1.0');        
    
    $this->delimited_types = array(
      new LuminousDelimiterRule("COMMENT", 0, "/*", "*/")
      );
      
    $this->simple_types = array(
      new LuminousSimpleRule("TYPE", LUMINOUS_REGEX, 
      "/[a-zA-Z\-]+[\s]*(?=[:])/"),
      new LuminousSimpleRule("VALUE", LUMINOUS_REGEX, 
        "/(?<=[:])[\s]*.+?(?=[;\n\r\}])/"),
      
      new LuminousSimpleRuleList("OPERATOR", 0, 
        array(';', ':', '#', '.'))
      );
  }
}


class LuminousGrammarCSSEmbedded extends LuminousGrammarCSS
{

  function __construct()
  {
    $this->ignore_outside = array(
      new LuminousDelimiterRule(null, LUMINOUS_REGEX|LUMINOUS_EXCLUDE, 
      "/(&lt;style.*?&gt;)/si", "/(&lt;\/style&gt;)/si")
      );
    $this->child_grammar = new LuminousGrammarHTML();
   
    parent::__construct();
  }
}

class LuminousGrammarJavaScript extends LuminousGrammar
{


  public $keywords =  array("break", "continue", "do", "for", "import", "new", 
    "void", "case", "default", "else", "function", "in", "return", 
    "while", "comment", "delete", "export", "if", "label", "switch", "with",
    "try", "catch");
    
  public $functions = array('typeof');
  public $types = array('this', 'var');
  
//   public $operators = array();
  
  public function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('js');
    $this->SetInfoVersion('1.0');    
    
    
    $this->delimited_types = array(
      new LuminousDelimiterRule("DOCCOMMENT", 0, '/**', '*/'),
      new LuminousDelimiterRule("DOCCOMMENT", 0, '/*!', '*/'),
      new LuminousDelimiterRule("DOCCOMMENT", 0, '//!', "\n"),
      new LuminousDelimiterRule("DOCCOMMENT", 0, '///', "\n"),
      new LuminousDelimiterRule("COMMENT", 0, '/*', '*/'),
      new LuminousDelimiterRule("COMMENT", LUMINOUS_STOP_AT_END, '//', "\n"),
      new LuminousDelimiterRule("STRING", 0, "'", "'", 
      'luminous_type_callback_generic_string'),
      new LuminousDelimiterRule("STRING", 0, '"', '"',
      'luminous_type_callback_generic_string'),  
      
      // I can't decide which is faster.
      
//       new LuminousDelimiterRule("REGEX", LUMINOUS_REGEX,
//         '/
//           (?<=([\(\[,=:;\?!]))
//           [\s]* 
//           \/[^\/\*]
//           /x', '/\/[igm]*/')
      
      new LuminousDelimiterRule("REGEX", LUMINOUS_REGEX|LUMINOUS_COMPLETE, 
        '/
        (?<=([\(\[,=:;\?!\|\&]))
        [\s]* 
        \/(?![\/\*])
        (?:.*?[^\\\])*?
        (?:\\\\\\\\)*\/
        [igm]*/x',
        null,
        'luminous_type_callback_generic_string'
      )
    );


    $this->SetSimpleTypeRules();
  }
  
  
}


class LuminousGrammarJavaScriptEmbedded extends LuminousGrammarJavaScript
{

  function __construct()
  {    
    $this->ignore_outside = array(
      new LuminousDelimiterRule(0, LUMINOUS_REGEX|LUMINOUS_EXCLUDE,
      "/(?:&lt;script.*?&gt;)/si", "/(?:&lt;\/?script&gt;)/si")
      );    
    $this->child_grammar = new LuminousGrammarCSSEmbedded();
    
    parent::__construct();
    
  }
}



class LuminousGrammarBash extends LuminousGrammar
{
  
  function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('sh');
    $this->SetInfoVersion('1.0');        
    
    $this->keyword_regex = '/(?<![a-zA-Z0-9_$\.])(?:%KEYWORD)(?![a-zA-Z0-9_\.])/';
    
    
    $this->numeric_regex = '
    /(?<![[:alnum:]_<$\.\-])  
    (
      #hex 
      (?:0[xX][0-9A-Fa-f]+)
    |
      # regular number
      (?:
        [0-9]+
        (?:
          # fraction
          \.[0-9]+([eE]?[0-9]+)?
        )?
      )
      |
      (?:
        # or only after the point, float x = .1;
        \.[0-9]+(?:[eE]?[0-9]+)?
      )
    )
    (?![[:alnum:]_<$\.\-]) 
    /x';
    
    
    $this->keywords = array_merge($this->keywords, 
      array("case", "do", "done", "elif", "else", "esac", "fi", "for",
    "function", "if", "in", "select", "then", "time", "until", "while")
    );
    
    $this->operators = array();
    
    // just some common ones or I'll be here all year.
    $this->functions = array("awk", "cat", 'cd', "chmod", "chown", "cp", "cut", 
      "date", "diff", "echo", "egrep", "env", "eval", "exit", "export", "file",
      "find", "ftp", "gawk", "grep", "gzip", "head", "help", 'join', 'less', 
      'ln', 'ls', 'mkdir', 'mv', 'ps', 'pwd', 'read', 'rename', 'rm', 'rmdir', 
      'sed', 'sleep', 'sort', 'ssh', 'sudo', 'su', 'tail', 'tar', 'time',
      'touch'); 
    
    $this->delimited_types = array(
      new LuminousDelimiterRule("SHEBANG", LUMINOUS_REGEX|LUMINOUS_COMPLETE, 
        "/^[\s]*#!.*?\n/"),
      new LuminousDelimiterRule("COMMENT", 0, "#", "\n"),
      new LuminousDelimiterRule("STRING", 0, "'", "'", 
        'luminous_type_callback_bash_string'),
      new LuminousDelimiterRule("STRING", 0, '"', '"',
        'luminous_type_callback_bash_string'),
        
      //obviously these are function calls, but it looks prettier if they're not.
      // and it's easier to read. Perhaps need a new identifier.
      new LuminousDelimiterRule("TYPE", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
      '/\$\([^\(]+\)/', null,
        'luminous_type_callback_bash_string'),
      new LuminousDelimiterRule('FUNCTION', 0, '`', '`',
        'luminous_type_callback_bash_string')  
      );
      
    $this->simple_types[] =     
      new LuminousSimpleRule("VARIABLE", LUMINOUS_REGEX,
        '/[[:alnum:]_-]*?[\s]*(?=[=])/m');
    $this->simple_types[] =     
        new LuminousSimpleRule("VARIABLE", LUMINOUS_REGEX,
        '/\${.*?}/m');
        
    $this->simple_types[] =         
      new LuminousSimpleRule('VARIABLE', LUMINOUS_REGEX,
        "/\\$[[:alnum:]_-]+/");
        
    // yes this again.
    $this->simple_types[] = 
      new LuminousSimpleRule('TYPE', LUMINOUS_REGEX, '/(?<![[:alnum:]_\$])\.\/.*?[^\s]([\s]|$)/');
         
    $this->SetSimpleTypeRules();
  }
}

class LuminousGrammarMakefile extends LuminousGrammarBash
{
  function __construct()
  {
    $this->keywords[] = "endif";
    $this->keywords[] = "ifdef";
    
    // dependency
    $this->simple_types[] = new LuminousSimpleRule('MAKE_DEP', LUMINOUS_REGEX,
    '/(^[[:alnum:]_\-\. ]+?:)(.*?$)/m', null, 2);
      
//     // Makefile make Rule.
    $this->simple_types[] = 
      new LuminousSimpleRule('MAKE_TARGET', LUMINOUS_REGEX, 
        '/^[[:alnum:]_\-\. \s]+?(?=[:])/m');
    parent::__construct();
        
  }
  
  
}





class LuminousGrammarPlain extends LuminousGrammar
{
  
  
  
  function __construct()
  {
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
                         'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('plain');
    $this->SetInfoVersion('1.0');      
    
    $this->simple_types = array(
      new LuminousSimpleRule('COMMENT', LUMINOUS_REGEX,
      '/^[\s]*#.*$/m')
    );
    
  }
}

class LuminousGrammarMATLAB extends LuminousGrammar
{

  public $keywords = array('break', 'case', 'catch', 'classdef', 'continue',
    'else', 'elseif','end', 'for', 'function', 'global', 'if', 'otherwise', 
    'parfor', 'persistent', 'return', 'spmd', 'switch', 'try', 'while');
    
  public function __construct()
  {
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('matlab');
    $this->SetInfoVersion('1.0');    
    
    
    $this->delimited_types = array(
      new LuminousDelimiterRule("COMMENT", 0, "%{", "}%"),
      new LuminousDelimiterRule("COMMENT", 0, "%", "\n"),
      new LuminousDelimiterRule("STRING",  LUMINOUS_REGEX|LUMINOUS_COMPLETE, 
        "/
        ('')
        |
        (('.*?(?<!')')(?!'))
        /sx", null, 'luminous_type_callback_sql_single_quotes')
    );
    
    $this->SetSimpleTypeRules();    
    
  }
}


class LuminousGrammarCSharp extends LuminousGrammar
{
  public $keywords = array("abstract", "event", "new", "struct", "as", 
    "explicit", "null", "switch", "base", "extern", "object", "this", "false", 
    "operator", "throw", "break", "finally", "out", "true","fixed", "override", 
    "try", "case", "params", "typeof", "catch", "for", "private", "foreach", 
    "protected", "checked", "goto", "public", "unchecked", "class", "if", 
    "readonly", "unsafe", "implicit", "ref", "continue", "in", "return", 
    "using", "decimal", "virtual", "default", "interface", "sealed", "volatile",
    "delegate", "internal", "void", "do", "is", "sizeof", "while", "lock", 
    "stackalloc", "else", "long", "static", "enum", "namespace");
  
  public $types = array("bool", "byte", "char", "const", "double", "float", "int",
  "long", "sbyte", "short", "uint", "ulong", "ushort", "string");
  
 function __construct()
  {
    
    
    $this->SetInfoAuthor( 
      array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
      'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('cs');
    $this->SetInfoVersion('1.0');    
    
    
    $this->delimited_types = array(
      new LuminousDelimiterRule("DOCCOMMENT", 0, "/**", "*/"),
      new LuminousDelimiterRule('DOCCOMMENT', 0, '///', "\n"),
      new LuminousDelimiterRule("COMMENT", 0, "/*", "*/"),
      new LuminousDelimiterRule("COMMENT", 0, "//", "\n"),
      new LuminousDelimiterRule("STRING", 0, '"', '"',
      'luminous_type_callback_cstring'),
      new LuminousDelimiterRule("CHARACTER", 0, "'", "'",
      'luminous_type_callback_cstring')
    );
    
    $this->SetSimpleTypeRules();
  }

}


class LuminousGrammarJava extends LuminousGrammar
{
  public $keywords = array("abstract", "continue", "for", "new", "switch",
"assert", "default", "goto", "package", "synchronized",
"do", "if", "private", "this",
"break", "implements", "protected", "throw",
"else", "import", "public", "throws",
"case", "enum", "instanceof", "return", "transient",
"catch", "extends", "try",
"final", "interface", "static", "void",
"class", "finally", "strictfp", "volatile",
"float", "native", "super", "while");

  public $types = array("byte", "const", "char", "double", "float", "int",
  "short", "long", "bool", "String");

  function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('java');
    $this->SetInfoVersion('1.0');        
    
    $this->delimited_types = array(
      new LuminousDelimiterRule("DOCCOMMENT", 0, "/**", "*/",
      'luminous_type_callback_doccomment'),
      new LuminousDelimiterRule("COMMENT", 0, "/*", "*/"),
      new LuminousDelimiterRule("COMMENT", 0, "//", "\n"),
      
      new LuminousDelimiterRule("STRING", 0, '"', '"',
      'luminous_type_callback_cstring'),
      new LuminousDelimiterRule("CHARACTER", 0, "'", "'",
      'luminous_type_callback_cstring')
      );
    $this->SetSimpleTypeRules();
      
  }
}


/** Normal Diff */
class LuminousGrammarDiff extends LuminousGrammar
{

  
  function __construct()
  {
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('diff');
    $this->SetInfoVersion('1.0');        
    
    $this->simple_types = array(
      new LuminousSimpleRule('DIFF_RANGE', LUMINOUS_REGEX, 
        '/^[0-9]+(,[0-9]+)?[acd]?[0-9]+(,[0-9]+)?$/mi'),
      new LuminousSimpleRule('DIFF_OLD', LUMINOUS_REGEX,
        '/^&lt;.*$/mi'),
      new LuminousSimpleRule('DIFF_NEW', LUMINOUS_REGEX,
        '/^\&gt;.*$/mi')
    );
    
  }
}


/** Unified Diff */
class LuminousGrammarUDiff extends LuminousGrammar
{

  
  function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('udiff');
    $this->SetInfoVersion('1.0');        
    
    $this->simple_types = array(
      new LuminousSimpleRule('DIFF_HEADER_NEW', LUMINOUS_REGEX,
        '/^\+{3}.*$/mi'),
        
      new LuminousSimpleRule('DIFF_HEADER_OLD', LUMINOUS_REGEX,
       '/^\-{3}.*$/mi'),        
        
      new LuminousSimpleRule('DIFF_RANGE', LUMINOUS_REGEX, 
        '/^@@.*@@$/mi'),
        
      new LuminousSimpleRule('DIFF_OLD', LUMINOUS_REGEX,
        '/^\-[^\-].*$/mi'),
        
      new LuminousSimpleRule('DIFF_NEW', LUMINOUS_REGEX,
       '/^\+[^\+].*$/mi')
    );
    
  }  
}


class LuminousGrammarHaskell extends LuminousGrammar
{

  public $keywords = array("as", "case", "of", "class", "data", "family",
    "instance", "default", "deriving", "do", "forall", "foreign", "hiding",
    "if", "then", "else", "import", "infix", "infixl", "infixr", "let", "in",
    "mdo", "module", "newtype", "proc", "qualified", "rec", "type", "where");
    
  public $types = array("Integer", "Char", "String", "Float");
  
  // Haskell's philosophy seems to be "you've got all those keys on your
  // keyboard and I'm not going to waste them"
  public $operators = array('\+', '\*', '-', '\/', '=', '&gt;', '&lt;', '=',
  '!', '%', '&amp;', '\|', '~', '\^', '\[', '\]', '\(', '\)', '\.', ':', '@'
  );
  
  public function __construct()
  {
    
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('hs');
    $this->SetInfoVersion('1.0');        
    
    
    
    $this->delimited_types = array(
      new LuminousDelimiterRule("STRING", 0, '"', '"', 
        'luminous_type_callback_generic_string'),
      new LuminousDelimiterRule("CHARACTER", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
        "/'(\\\\)?.'/"),
      new LuminousDelimiterRule("FUNCTION", 0, "`", "`"),
      new LuminousDelimiterRule("FUNCTION", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
      "/\\\\.*?[\s]/"),
      new LuminousDelimiterRule("COMMENT", 0, "--", "\n"),      
      
      new LuminousDelimiterRule("COMMENT", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
      // Haskell's comments can be nested which is all very nice but 
      // I think that it's computationally impossible to validate arbtrary 
      // depth bracket nesting with a regex.
      // This one goes to depth 2.
      "/
      \{\-
        (.*?
        (\{\-.*?\-\})?
        )*?
      \-\}
      /xs")
      );    
      
    $this->SetSimpleTypeRules();  
  }
  
}




class LuminousGrammarSQL extends LuminousGrammar
{
  
  public $keyword_regex =  "/(?<![a-zA-Z0-9_$])%KEYWORD(?![a-zA-Z0-9_])/i";
  public $keywords = array("ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER",
  "ANALYZE", "AND", "AS", "ASC", "ATTACH", "AUTO(?:_)?INCREMENT", "BEFORE", "BEGIN",
  "BETWEEN", "BY", "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN",
  "COMMIT", "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE",
  "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE",
  "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", "ELSE",
  "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", "FAIL", "FOR",
  "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", "IGNORE",
  "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", "INSERT",
  "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", "LEFT",
  "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", "NULL", "OF",
  "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", "PRIMARY", "QUERY",
  "RAISE", "REFERENCES", "REGEXP", "REINDEX", "RELEASE", "RENAME", "REPLACE",
  "RESTRICT", "RIGHT", "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE",
  "TEMP", "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE",
  "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE");
  
  public $type_regex =  "/(?<![a-zA-Z0-9_$])(:?%TYPE)(?![a-zA-Z0-9_])/i";
  
  public $types = array("(?:tiny|small|medium|big)?int(?:eger)?", "(?:var)?char",
  "(?:tiny|medium|long)?text", "(?:long)?blob", "float", "double", "decimal", 
  "data(?:time)?", "time(?:stamp)?");
  
  
  public function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('sql');
    $this->SetInfoVersion('1.0');        
    
    
    $this->delimited_types = array(
      new LuminousDelimiterRule("COMMENT", 0, "--", "\n"),
//       new LuminousDelimiterRule("STRING", 0, '\'', '\''), 
        
      new LuminousDelimiterRule("STRING", LUMINOUS_REGEX|LUMINOUS_COMPLETE, 
        "/
        (?:'')
        |
        (?:(?:'.*?(?<!')')(?!'))
        /sx", null, 'luminous_type_callback_sql_single_quotes'),
      new LuminousDelimiterRule("STRING", 0, "`", "`",
        'luminous_type_callback_generic_string'),
      new LuminousDelimiterRule("STRING", 0, '"', '"',
        'luminous_type_callback_generic_string')
      );
      
    $this->SetSimpleTypeRules();
    
    
  }

}

///\todo: named operators.
///\todo: variable interpolation
class LuminousGrammarPerl extends LuminousGrammar
{
  public $keywords = array("my", "print",
     "caller",
     "continue",
     "die",
     "do",
     "dump",
     "else",
     "elsif",
     "eval",
     "exit",
     "for",
     "foreach",
     "goto",
     "import",
     "if",
     "last",
     "local",
     "next",
     "prototype",
     "redo",
     "return",
     "sub",
     "use",
     "wantarray",
     "while");
 
  public $ignore_outside_strict = false;
  
  
  
  
  
  public function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('pl');
    $this->SetInfoVersion('1.0');   
    
    
    
    $this->delimited_types = array(
      new LuminousDelimiterRule('SHEBANG', LUMINOUS_REGEX|LUMINOUS_COMPLETE, 
      "/^[\s]*#!.*?\n/"),      
      new LuminousDelimiterRule("FUNCTION", 0, '`', '`'),
      new LuminousDelimiterRule("COMMENT", 0, "#", "\n"),
      new LuminousDelimiterRule("STRING", LUMINOUS_EXCLUDE, '"', '"'),
      new LuminousDelimiterRule("STRING", LUMINOUS_EXCLUDE, '\'', '\''),
      
      new LuminousDelimiterRule("STRING",       
        LUMINOUS_REGEX|LUMINOUS_DYNAMIC_DELIMS|LUMINOUS_COMPLETE|LUMINOUS_EXCLUDE,
        '/(?<![a-zA-Z0-9_\$])q[qxw]?[\s]*(?![a-zA-Z0-9])/'),
      new LuminousDelimiterRule("VALUE", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
       "/&lt;(STDIN|STDOUT|STDERR|DATA)&gt;/"),
       
       // I don't know if these next two are right.
       new LuminousDelimiterRule("REGEX", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
        '/
          (?<=([\(\[,=:;\?!~]))
          [\s]* 
          (m|qr)?\/
            (.*?[^\\\])*?
          (\\\\\\\\)*\/
          [cgimosx]*/x', null, 'luminous_type_callback_generic_string'),        
      
       new LuminousDelimiterRule("REGEX", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
        '/
          (?<=([\(\[,=:;\?!~]))
          [\s]* 
          (s|tr|y)\/
            ((.*?[^\\\])*?
          (\\\\\\\\)*\/){2}
          [cdsegimosx]*/x',       
        null, 'luminous_type_callback_generic_string')
       );       

    $this->ignore_outside = array( 
      new LuminousDelimiterRule(0, LUMINOUS_REGEX, "/^/", 
      "/__(DATA|END)__/")
      );
      
      
      // this isn't really a type, but what else do you call it?
      $this->simple_types[] = new LuminousSimpleRule('TYPE',
        LUMINOUS_REGEX, '/&lt;[[:alnum:]_]+&gt;/');
      
      
      $this->simple_types[] = new LuminousSimpleRule('VARIABLE',
        LUMINOUS_REGEX, "/(?!<[a-z0-9_])[$%@][a-z0-9_]+/i");
        
      $this->simple_types[] = new LuminousSimpleRule('VALUE',
        LUMINOUS_REGEX, "/(?<=::)(?>[a-z0-9_]+)[\s]*(?!\()/i");        
      
      
      $this->SetSimpleTypeRules();
        

      $this->simple_types[] = new LuminousSimpleRule('VALUE',
        LUMINOUS_REGEX, "/__(DATA|END)__/");  
  }
  

}

class LuminousGrammarPHP extends LuminousGrammar
{

  public $operators = array('\+', '\*', '-', '\/', '=', '&gt;', 
    '&lt;', '=', '!', '%', '&amp;', '\|', '~', '\^', '\[', '\]');
  
  public $keywords = array(
  "&lt;\?(php)?", "\?&gt;",
  "abstract", "and",  "as", "break",
  "case", "catch", "cfunction", "class", "Class", "clone",
  "const", "continue", "declare", "default", "do",
  "echo","else", "elseif", "enddeclare", "endfor", "endforeach",
  "endif", "endswitch", "endwhile", "extends", "final",
  "for", "foreach", "function", "global", "goto",
  "if", "implements", "interface", "instanceof",
  "namespace", "new", "old_function", "or", "private",
  "protected", "public", "return", "static", "switch", "throw",
  "try", "use", "var", "while", "xor" );

  public $functions = array("include(_once)?", "require(_once)?", "array", 
    "count");
    
  public $types = array('false', 'null', 'true');
  
  public function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('php');
    $this->SetInfoVersion('1.0');    
    
    
    $this->ignore_outside =  array(
      new LuminousDelimiterRule(null, LUMINOUS_REGEX, 
    "/&lt;\?(php)?/", "/\?&gt;/")
    );
  
    
    $this->delimited_types = array(
      new LuminousDelimiterRule("DOCCOMMENT", 0, "/**", "*/",
        'luminous_type_callback_doccomment'),
      new LuminousDelimiterRule("DOCCOMMENT", 0, "///", "\n",
        'luminous_type_callback_doccomment'),        
      new LuminousDelimiterRule("COMMENT", 0, "/*", "*/"),
      new LuminousDelimiterRule("COMMENT", LUMINOUS_STOP_AT_END, "//", "\n"),
      new LuminousDelimiterRule("COMMENT", LUMINOUS_STOP_AT_END, "#", "\n"),
      new LuminousDelimiterRule("STRING", 0, "'", "'",
        'luminous_type_callback_php_sstring'),
        
      new LuminousDelimiterRule("STRING", 0, '"', '"',
      'luminous_type_callback_php_dstring'
      )
      );
    $this->child_grammar = new LuminousGrammarJavaScriptEmbedded();
    
    $this->SetSimpleTypeRules();
    $this->simple_types[] = new LuminousSimpleRule('VARIABLE', LUMINOUS_REGEX, 
    "/\\$[a-z_][a-z0-9_]*/i");
  }
  
}




class LuminousGrammarVisualBasic extends LuminousGrammar 
{
  
  
  public $operators = array("\+", "\-", "&amp;", "=", "\*", "\^", "\/",  
  "(?<![a-z0-9])and(also?)(?![a-z0-9])", "(?<![a-z0-9])or(else)?(?![a-z0-9])",
  '(?<![a-z0-9])not(?![a-z0-9])', '(?<![a-z0-9])xor(?![a-z0-9])'
  );


  public $types = array(
    "boolean",
    "byte",
    "c(bool|byte|char|date|dec|dbl|int|lng|obj|short|sng|str|type)",
    "char",
    "date",
    "decimal",
    "double",
    "enum",
    "false",
    "integer",
    "long",
    "short",
    "string",
    "true");
    
  // HOW MANY?
  public $keywords = array(
    "addhandler", "addressof", "alias", "ansi", "as", "assembly", "auto",
    "byref", "byval", "call", "case", "catch", "const", "declare", "default",
    "delegate", "dim", "directcast", "do", "each", "else(if)?", "end", "erase",
    "error", "event", "exit", "finally", "for", "friend", "function", 
    "get(type)?", "gosub", "goto", "handles", "if", "implements", "interface",
    "let", "Lib", "like", "loop", "me", "mod", "module", "mustinheret", 
    "mustoverride", "mybase", "myclass", "namespace", "new", "next", "nothing",
    "on", "option", "optional", "overloads", "overridable", "overrides",
    "paramarray", "preserve", "private", "property", "protected", "public", 
    "raiseevent", "readonly", "return", "select", "set", "shadows", "shared",
    "single", "static", "step", "stop", "structure", "sub", "synclock", "then",
    "throw", "to", "try", "typeof", "unicode", "until", "variant", "when", 
    "while", "with", "withevents", "writeonly"
  );
  
  
  
  public $escape_chars = array();
  
  

  public function __construct()
  {
    $this->case_insensitive = true;
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('vb');
    $this->SetInfoVersion('1.0');        
    
    $this->delimited_types = array(
      new LuminousDelimiterRule("DOCCOMMENT", 0, "'''", "\n"),
      new LuminousDelimiterRule("COMMENT", 0, "'", "\n"),
      new LuminousDelimiterRule("STRING", 0, '"', '"'),
      new LuminousDelimiterRule("PREPROCESSOR", 
        LUMINOUS_REGEX|LUMINOUS_COMPLETE, "/^#.*?(?=($|\"))/m")
    );
    
    $this->SetSimpleTypeRules();
    
  }
  
}

/// \endcond

?>
